﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media.Animation;

namespace Comarch.Animation.SL5Example
{
    public class DataLayer : INotifyPropertyChanged
    {
        private ObservableCollection<SingleAnimation> _singleAnimations;
        public ObservableCollection<SingleAnimation> SingleAnimations
        {
            get { return _singleAnimations; }
            set { _singleAnimations = value;
            OnPropentyChanged("SingleAnimations");
            }
        }

        public List<IEasingFunction> EasingFunctions { get; set; }
        public IEasingFunction EasingFunction { get; set; }

        private int _duration;
        public int Duration
        {
            get { return _duration; }
            set
            {
                value = CheckDuration(value);
                _duration = value;
                OnPropentyChanged("Duration");
                UpdateAnimations();
            }
        }

        private static int CheckDuration(int value)
        {
            if (value < 0)
                return -value;
            return value;
        }
        
        private int _initialOffset;
        public int InitialOffset
        {
            get { return _initialOffset; }
            set
            {
                _initialOffset = value;
                OnPropentyChanged("InitialOffset");
            }
        }

        private int _delayBetweenElements;
        public int DelayBetweenElements
        {
            get { return _delayBetweenElements; }
            set
            {
                _delayBetweenElements = value;
                OnPropentyChanged("DurationBetweenObjects");
            }
        }

        public DataLayer()
        {
            Duration = 400;
            InitialOffset = 0;
            DelayBetweenElements = 120;
            EasingFunction = new CubicEase();
            AddEasingFunctions();
        }

        private void UpdateAnimations()
        {
           AddData();
        }

        private void AddEasingFunctions()
        {
            EasingFunctions = new List<IEasingFunction> {new CubicEase(), new BounceEase(), new PowerEase()};
        }

        private void AddData()
        {
            SingleAnimations = new ObservableCollection<SingleAnimation>
                                   {
                                       new SingleAnimation
                                           {
                                               AnimationName = "OffsetFadeIn",
                                               Animation = OffsetFadeIn,
                                               AnimationDescription =
                                                   String.Format(
                                                       "sbb.EntranceEffects.OffsetFadeIn(element,{0},FlyDirection.Right,150));",
                                                       Duration)
                                           },
                                       new SingleAnimation
                                           {
                                               AnimationName = "AddWidthEntry",
                                               Animation = AddWidthEntry,
                                               AnimationDescription =
                                                   String.Format(
                                                       "sbb.EntranceEffects.AddWidthEntry(element, {0}, EasingFunction);",
                                                        Duration)
                                           },
                                       new SingleAnimation
                                           {
                                               AnimationName = "AddHeightEntry",
                                               Animation = AddHeightEntry,
                                               AnimationDescription =
                                                   String.Format(
                                                       "sbb.EntranceEffects.AddHeightEntry(element, {0}, EasingFunction);",Duration)
                                           },
                                       new SingleAnimation
                                           {
                                               AnimationName = "FadeIn",
                                               Animation = FadeIn,
                                               AnimationDescription =
                                                   String.Format(
                                                       "sbb.EntranceEffects.FadeIn(element, {0}, EasingFunction);",
                                                       Duration)
                                           },
                                       new SingleAnimation
                                           {
                                               AnimationName = "SmallShake",
                                               Animation = SmallShake,
                                               AnimationDescription =
                                                   String.Format("sbb.EmphasisEffects.SmallShake(element, {0});",
                                                                 Duration)
                                           },
                                       new SingleAnimation
                                           {
                                               AnimationName = "ZoomInAndBack",
                                               Animation = ZoomInAndBack,
                                               AnimationDescription =
                                                   String.Format("sbb.EmphasisEffects.ZoomInAndBack(element, {0});",
                                                                 Duration)
                                           },
                                   };
        }

        private void FlyInEffect(FrameworkElement element, StoryboardBuilder sbb)
        {
            element.Opacity = 0;
            sbb.EntranceEffects.FlyIn(element, Duration, FlyDirection.Left, EasingFunction);
        }

        private void OffsetFadeIn(FrameworkElement element, StoryboardBuilder sbb)
        {
            element.Opacity = 0;
            sbb.EntranceEffects.OffsetFadeIn(element, Duration, FlyDirection.Right, 150);
        }

        private void AddWidthEntry(FrameworkElement element, StoryboardBuilder sbb)
        {
            element.Opacity = 0;
            sbb.EntranceEffects.AddWidthEntry(element, Duration, EasingFunction);
        }

        private void AddHeightEntry(FrameworkElement element, StoryboardBuilder sbb)
        {
            element.Opacity = 0;
            sbb.EntranceEffects.AddHeightEntry(element, Duration, EasingFunction);
        }

        private void FadeIn(FrameworkElement element, StoryboardBuilder sbb)
        {
            element.Opacity = 0;
            sbb.EntranceEffects.FadeIn(element, Duration, EasingFunction);
        }

        private void ZoomInAndBack(FrameworkElement element, StoryboardBuilder sbb)
        {
            sbb.RenderTransformOrigin = new Point(0.5, 0.5);
            sbb.EmphasisEffects.ZoomInAndBack(element, Duration);
        }

        private void SmallShake(FrameworkElement element, StoryboardBuilder sbb)
        {
            sbb.EmphasisEffects.SmallShake(element, Duration);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropentyChanged(string name)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(name));
        }
    }
}